
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package model;

import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import exception.InvalidCommandException;
import exception.InvalidCommandResultReferenceException;
import java.lang.Thread.State;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author think
 */
@Singleton
public class CommandRunner {

    private  Queue<Executable> queuedCommands = new LinkedList<Executable>();
    private  List<Executable> runningCommands = new LinkedList<Executable>();
    private  CommandRunnnerThread runnerThread = new CommandRunnnerThread();
    private  boolean run;

    @Inject
    CommandResultManager commandResultManager;

//    @Inject
//    public CommandRunner(CommandResultManager resultManager){
//        this.commandResultManager = resultManager;
//    }

    public CommandRunner() {
        runnerThread.start();
    }

    public void reset() {
        runningCommands.clear();
        queuedCommands.clear();
    }

    public CommandRunnnerThread getRunnerThead() {
        return runnerThread;
    }

    public void addCommand(Executable cmd) {
        queuedCommands.add(cmd);
    }

    public Queue getQueuedCommands() {
        return queuedCommands;
    }

    public List getRunningCommands() {
        return runningCommands;
    }

    public void showRunningCommands() {
        Iterator it = runningCommands.iterator();
        System.out.println("running command:");
        while (it.hasNext()) {
            Executable cmd = (Executable) it.next();
            System.out.println(cmd.getCmd());
        }

    }

    public void pause() {
        synchronized (runnerThread) {
            runnerThread.pause = true;
        }
    }

    public void resume() {
        synchronized (runnerThread) {
            runnerThread.pause = false;
            runnerThread.notify();
        }
    }

    public boolean isRunning() {
        State state = runnerThread.getState();
        if (state == State.WAITING) {
            return false;
        } else {
            return true;
        }
    }

    public boolean isCommandRunning(String cmd) {
        Iterator it = runningCommands.iterator();
        while (it.hasNext()) {
            Command command = (Command) it.next();
            if (command.getCmd().equalsIgnoreCase(cmd)) {
                return true;
            }
        }
        return false;
    }

    public boolean isCommandQueued(String cmd) {
        Iterator it = queuedCommands.iterator();
        while (it.hasNext()) {
            Command command = (Command) it.next();
            if (command.getCmd().equalsIgnoreCase(cmd)) {
                return true;
            }
        }
        return false;
    }

//    public static void main(String[] args) {
////        TSRunner.start();
//        CommandRunner.resume();
//        Command cmd1 = new Command("help");
//        Command cmd2 = new Command("qma");
//        Command cmd3 = new Command("qm win03uepinstall");
//        CommandRunner.addCommand(cmd1);
//        CommandRunner.addCommand(cmd2);
//        CommandRunner.addCommand(cmd3);
//        try {
//            Thread.sleep(10000);
//        } catch (InterruptedException ex) {
//            Logger.getLogger(CommandRunner.class.getName()).log(Level.SEVERE, null, ex);
//        }
//        System.out.println(CommandRunner.getRunningCommands().size());
//        System.out.println(CommandRunner.getQueuedCommands().size());
//        System.out.println(cmd1.getOutput());
//        System.out.println(cmd2.getOutput());
//        System.out.println(cmd3.getOutput());
//    }

    @Singleton
    public class CommandRunnnerThread extends Thread {
//        private CommandResultManager resultManager = Guice.createInjector().getInstance(CommandResultManager.class);
        boolean pause = false;
        private CommandRunner parent;

        public CommandRunnnerThread() {
            pause = false;
//            run();
        }

        @Override
        public void run() {
            while (true) {
                try {
                    synchronized (this) {
                        while (pause) {
                            this.wait();
                        }
                        if (getRunningCommands().size() > 0) {
                            Iterator it = getRunningCommands().iterator();
                            while (it.hasNext()) {
                                Executable cmd = (Executable) it.next();
                                if (cmd.finished()) {
                                    commandResultManager.addResult(cmd);
//                                    resultManager.addResult(cmd);
                                    it.remove();
                                }
                            }
                        }
                        if (getQueuedCommands().size() > 0) {
                            Executable cmd = (Executable) getQueuedCommands().peek();
                            if (!isCommandRunningOnMachine(cmd.getMachine())) {
                                cmd = (Executable) getQueuedCommands().poll();
                                getRunningCommands().add(cmd);
                                try {
                                    cmd.run();
                                } catch (InvalidCommandException ex) {
                                    cmd.setResult(new CommandResult(1, ex.getMessage()));
                                } catch (InvalidCommandResultReferenceException ex) {
                                    cmd.setResult(new CommandResult(1, ex.getMessage()));
                                } 
//                                CommandResultManager.addResult(cmd);

                            }
                        }

                    }
                    Thread.sleep(100);
                } catch (InterruptedException ex) {
                    Logger.getLogger(CommandRunner.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }

        boolean isCommandRunningOnMachine(Machine machine) {
            Iterator it = getRunningCommands().iterator();
            while (it.hasNext()) {
                Command cmd = (Command) it.next();
                if (cmd.getMachine() != null && cmd.getMachine().equals(machine)) {
                    return true;
                }
            }
            return false;
        }
    }
}

